import { ModelTreeObjectType } from '@/common/types';
import { Tree, TreeProps } from 'antd';
import { BasicDataNode, EventDataNode } from 'antd/es/tree';
import React, { ComponentType, useEffect, useRef, useState } from 'react';
import styled from 'styled-components';

/**
 * 模型树节点数据类型
 */
export type ModelTreeNodeType = ModelTreeObjectType & BasicDataNode;
/**
 * 修改了ant-tree默认样式后的Tree组件
 */
const StyledTree: ComponentType<TreeProps<ModelTreeNodeType>> = styled(
  Tree<ModelTreeNodeType>,
)`
  background: transparent;

  & .ant-tree-node-content-wrapper {
    display: flex;

    &:hover {
      background-color: #c1c0ee;
    }
  }

  /* 节点文字不换行 */
  & .ant-tree-node-content-wrapper {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 180px;
  }

  /* 禁止选中文字 */
  & .ant-tree-title {
    user-select: none;
  }

  /* 修改被选中节点的颜色 */
  &
    .ant-tree-node-content-wrapper:not(
      .ant-tree-node-disabled
    ).ant-tree-node-selected {
    color: #fff;
    background-color: #4e4ede;
  }

  /* 文档对象是隐藏状态，label的颜色
  & .ant-tree-node-content-wrapper .doc-obj-node-invisible {
    color: rgba(0, 0, 0, 0.45);
  }
  & .ant-tree-node-selected {
    .doc-obj-node-invisible {
      color: rgba(255, 255, 255, 0.8);
    }
  }

  /* 修改 switcher 的间距 */
  .ant-tree-switcher {
    margin-inline-end: 0px;
  }

  /* 单独修改 treenode 的 margin-bottom */
  && .ant-tree-treenode {
    margin-bottom: 0px;
  }
`;
export interface ITitleRenderProps {
  /**
   * 双击回调，一般用于需要对树节点进行编辑时
   * @param data 双击的树节点
   * @returns
   */
  onDoubleClick?: (data: ModelTreeObjectType) => void;
  /**
   * 悬停在TreeNode
   * @param data 悬停的节点数据
   * @param hovered 是否悬停
   */
  onHover?: (data: ModelTreeObjectType, hovered: boolean) => void;
}
/**
 * 高阶组件函数，为 Ant Design Tree 的每个节点生成自定义标题渲染器
 */
const withNodeTitleRenderer = (props: ITitleRenderProps) => {
  return (nodeData: ModelTreeNodeType) => {
    return (
      <TitleRender
        titleData={nodeData}
        onDoubleClick={props.onDoubleClick}
        onHover={props.onHover}
      />
    );
  };
};
/**
 * Ant Design 的 Tree 把 title 渲染在 <span> 中，
 * 这里监听整个 TreeNode 的双击（不仅限于 span）
 */
const TitleRender = ({
  titleData,
  onDoubleClick,
  onHover,
}: {
  titleData: ModelTreeNodeType;
  onDoubleClick?: (data: ModelTreeObjectType) => void;
  /**
   * 悬停在TreeNode
   * @param data 悬停的节点数据
   * @param hovered 是否悬停
   */
  onHover?: (data: ModelTreeObjectType, hovered: boolean) => void;
}) => {
  const { visibility } = titleData;
  const titleElement = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const nodeElement = titleElement.current.parentElement?.parentElement;

    const handleDoubleClick = () => {
      onDoubleClick?.(titleData);
    };
    const handleMouseEnter = () => {
      onHover?.(titleData, true);
    };

    const handleMouseLeave = () => {
      onHover?.(titleData, false);
    };

    nodeElement?.addEventListener('dblclick', handleDoubleClick);
    // 监听鼠标进入/离开，来触发hover事件
    nodeElement?.addEventListener('mouseenter', handleMouseEnter);
    nodeElement?.addEventListener('mouseleave', handleMouseLeave);

    return () => {
      nodeElement?.removeEventListener('dblclick', handleDoubleClick);
      nodeElement?.removeEventListener('mouseenter', handleMouseEnter);
      nodeElement?.removeEventListener('mouseleave', handleMouseLeave);
    };
  }, [titleData, onDoubleClick]);

  // TODO 使用class还有点问题，先使用style，后面优化
  // const classNames: string[] = [];
  // if (!visibility) {
  //   classNames.push('doc-obj-node-invisible');
  // }
  return (
    <span
      ref={titleElement}
      // className={classNames.join(' ')}
      style={{
        fontWeight: '',
        color: visibility ? undefined : 'rgba(0, 0, 0, 0.45)',
      }}>
      {titleData.label}
    </span>
  );
};
/**
 * 模型树组件的参数
 */
export interface ITreeProps extends ITitleRenderProps {
  /**
   * 模型树初始化数据
   */
  initialData: ModelTreeObjectType[];
  /**
   * 右键菜单回调，可显示右键菜单
   * @param event
   * @param data
   * @returns
   */
  onContextMenu?: (event: MouseEvent, data: ModelTreeObjectType[]) => void;
  /**
   * 选中回调
   * @param dxid 选中的节点的dxid数组
   */
  onSelected?: (dxid: string[]) => void;
}
/**
 * 模型树，展示导入的模型（网格/点云）及进行操作后的节点展示
 * @param props
 * @returns
 */
export default function ModelTree({
  initialData,
  onContextMenu,
  onSelected,
  onDoubleClick,
  onHover,
}: ITreeProps) {
  const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]); // 设置选中的树节点
  const [lastSelectedKey, setLastSelectedKey] = useState<React.Key>(); // 最后选中的，用于shift多选判断范围

  /**
   * 数据格式化，将树结构转换为 Ant Design Tree 组件所需的格式
   * @param nodes 树节点数组
   * @returns 格式化后的树节点数组
   */
  const formatData = (nodes: ModelTreeObjectType[]): ModelTreeNodeType[] =>
    nodes.map((item) => {
      if (Array.isArray(item.children)) {
        item.children = formatData(item.children);
      }
      // const icon = (
      //   <Icons
      //     name={item.iconName}
      //     defaultName='Icon_Default'
      //   />
      // );
      return {
        ...item,
        key: item.dxid,
        // icon,
      };
    });
  /**
   * 递归获取所有节点和子节点的key
   */
  const getAllKeys = (node: ModelTreeNodeType[], keys = []) => {
    node.forEach((item) => {
      keys.push(item.dxid); // dxid就是key
      if (item.children) {
        getAllKeys(item.children, keys);
      }
    });
    return keys;
  };
  /**
   * 树节点选中回调，处理单选、（ctrl、shift）多选
   */
  const handleOnSelect = (
    keys: React.Key[],
    {
      node,
      nativeEvent,
    }: {
      node: EventDataNode<ModelTreeNodeType>;
      nativeEvent: MouseEvent;
    },
  ) => {
    const currentKey = node.key;

    // 单选/多选逻辑和windows文件资源管理器的逻辑一致
    if (nativeEvent.ctrlKey) {
      // antd 树组件的 ctrl 多选，会自动处理选中的范围
      setLastSelectedKey(currentKey);
    } else if (nativeEvent.shiftKey) {
      // 处理shift多选
      if (lastSelectedKey) {
        const allKeys = getAllKeys(initialData);
        // 找到当前节点和上次选中节点的索引
        const currentIndex = allKeys.indexOf(currentKey);
        const lastIndex = allKeys.indexOf(lastSelectedKey);
        if (currentIndex !== -1 || lastIndex !== -1) {
          // 找到选中范围
          const range = allKeys.slice(
            Math.min(currentIndex, lastIndex),
            Math.max(currentIndex, lastIndex) + 1,
          );
          keys = range;
        }
      }
    } else {
      // 单选
      keys = [node.key];
      setLastSelectedKey(currentKey);
    }
    setSelectedKeys(keys);
    onSelected?.(keys as string[]);
    return keys;
  };
  /**
   * 树节点右键回调，处理右键菜单
   */
  const handleOnRightClick = ({
    event,
    node,
  }: {
    event: React.MouseEvent<Element, MouseEvent>;
    node: EventDataNode<ModelTreeNodeType>;
  }) => {
    let keys = selectedKeys;
    // 若当前点击的节点未被选中，则选中该节点
    if (!selectedKeys.includes(node.key)) {
      keys = handleOnSelect([node.key], {
        node,
        nativeEvent: event.nativeEvent,
      });
    }
    // 根据选中的key，获取选中的节点
    const selectedNodes = keys.map((key) => {
      const node = findNodeByKey(initialData, key);
      return node;
    });

    onContextMenu?.(event.nativeEvent, selectedNodes);
  };
  if (!initialData || initialData.length === 0) {
    // 没有数据或数据为空，不渲染树
    return <></>;
  }
  return (
    <StyledTree
      style={{ background: 'transparent', pointerEvents: 'auto' }}
      titleRender={withNodeTitleRenderer({ onDoubleClick, onHover })}
      showIcon
      treeData={formatData(initialData)}
      onSelect={handleOnSelect}
      onRightClick={handleOnRightClick}
      showLine={{ showLeafIcon: false }}
      selectedKeys={selectedKeys}
      defaultExpandAll
      virtual
      blockNode
      multiple
    />
  );
}
function findNodeByKey(initialData: ModelTreeObjectType[], key: React.Key) {
  // 递归查找
  for (const item of initialData) {
    if (item.dxid === key) {
      return item;
    }
    if (item.children) {
      const found = findNodeByKey(item.children, key);
      if (found) {
        return found;
      }
    }
  }
  return null;
}
